﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace ttlang.semantic
{
    public static class SystemModule
    {
        public static TTType typeVoid
        {
            get;
            private set;
        }
        public static TTType typeInt8
        {
            get;
            private set;
        }
        public static TTType typeInt16
        {
            get;
            private set;
        }
        public static TTType typeInt32
        {
            get;
            private set;
        }
        public static TTType typeUInt8
        {
            get;
            private set;
        }
        public static TTType typeUInt16
        {
            get;
            private set;
        }
        public static TTType typeUInt32
        {
            get;
            private set;
        }

        public static TTType typeString
        {
            get;
            private set;
        }
        public static TTType typeFloat
        {
            get;
            private set;
        }
        public static TTType typeFloat64
        {
            get;
            private set;
        }
        public static TTType typeBool
        {
            get;
            private set;
        }

        internal static void Init()
        {


            //ttlangCore = new Module("$ttlang.core");
            //添加一個系統類型
            //这样手工注册不是个事儿，要利用ttlang自身进行基本类库的声明

            //typeVoid = new TTType(ttlangCore, null, "void", DEFINETYPE.PRIMITIVE, true);
            //typeInt8 = new TTType(ttlangCore, null, "int8", DEFINETYPE.PRIMITIVE, true);
            //typeInt16 = new TTType(ttlangCore, null, "int16", DEFINETYPE.PRIMITIVE, true);
            //typeInt32 = new TTType(ttlangCore, null, "int32", DEFINETYPE.PRIMITIVE, true);
            //typeUInt8 = new TTType(ttlangCore, null, "uint8", DEFINETYPE.PRIMITIVE, true);
            //typeUInt16 = new TTType(ttlangCore, null, "uint16", DEFINETYPE.PRIMITIVE, true);
            //typeUInt32 = new TTType(ttlangCore, null, "uint32", DEFINETYPE.PRIMITIVE, true);
            //typeString = new TTType(ttlangCore, null, "string", DEFINETYPE.STRING, true);
            //typeFloat = new TTType(ttlangCore, null, "float", DEFINETYPE.PRIMITIVE, true);
            //typeFloat64 = new TTType(ttlangCore, null, "float64", DEFINETYPE.PRIMITIVE, true);
            //typeBool=new TTType(ttlangCore, null, "bool", DEFINETYPE.PRIMITIVE,true);
            //typeMath = new TTType(ttlangCore, null, "Math", DEFINETYPE.CLASS, true);




            //ttlangCore._defNameSpace.AddType(typeVoid);

            //ttlangCore._defNameSpace.AddType(typeString);

            //ttlangCore._defNameSpace.AddType(typeInt8);
            //ttlangCore._defNameSpace.AddType(typeInt16);
            //ttlangCore._defNameSpace.AddType(typeInt32);
            //ttlangCore._defNameSpace.AddType(typeUInt8);
            //ttlangCore._defNameSpace.AddType(typeUInt16);
            //ttlangCore._defNameSpace.AddType(typeUInt32);

            //ttlangCore._defNameSpace.AddType(typeFloat);
            //ttlangCore._defNameSpace.AddType(typeFloat64);
            //ttlangCore._defNameSpace.AddType(typeBool);

            //ttlangCore._defNameSpace.AddType(typeMath);


            //load define file.
            Assembly _assembly = Assembly.GetExecutingAssembly();
            string corett = "";
            using (var s = _assembly.GetManifestResourceStream("libttlang_compiler.core.t"))
            {
                byte[] data = new byte[s.Length];
                s.Read(data, 0, data.Length);
                corett = System.Text.Encoding.UTF8.GetString(data);
                if (corett[0] == 0xfeff)
                    corett = corett.Substring(1);
            }

            //compile default module.
            compiler.CompilerContext ttc = new compiler.CompilerContext();
            var parser = ttlang.src.AntlrTool.GetParserInfo<libttlang_parser.ttlangLexer, libttlang_parser.ttlangParser>("doc");
            var filenode = parser.ParseAst(corett, false, false, false);
            CompilerElement.Parse(ttc, "core", filenode);
            CompilerElement.Compile2Pass_NameSpace(ttc, ttc.module._defNameSpace);


            ttlangCore = new Module("$ttlang.core");
            ttlangCore._defNameSpace = ttc.module._defNameSpace;

            ////添加入口点定义，这个之后还得改
            //var entrypoint = new TTMethod(ttlangCore._defNameSpace, "EntryPoint", new TTArg[0], typeVoid);
            //ttlangCore._defNameSpace.AddMethod(entrypoint);

            //收集常用类型
            typeVoid = ttlangCore._defNameSpace.types["void"];
            typeBool = ttlangCore._defNameSpace.types["bool"];
            typeString = ttlangCore._defNameSpace.types["string"];
            typeInt8 = ttlangCore._defNameSpace.types["int8"];
            typeUInt8 = ttlangCore._defNameSpace.types["uint8"];
            typeInt16 = ttlangCore._defNameSpace.types["int8"];
            typeUInt16 = ttlangCore._defNameSpace.types["uint8"];
            typeInt32 = ttlangCore._defNameSpace.types["int8"];
            typeUInt32 = ttlangCore._defNameSpace.types["uint8"];
            typeFloat = ttlangCore._defNameSpace.types["float"];
            typeFloat64 = ttlangCore._defNameSpace.types["float64"];
        }
        static void InitConsole()
        {
            var typeConsole = new TTType(ttlangCore, null, "Console", DEFINETYPE.CLASS, true);
            ttlangCore._defNameSpace.AddType(typeConsole);
            var logmethod = new TTMethod(typeConsole, "Log", new TTArg[] { new TTArg(typeString, "_txt") }, typeVoid);
            var warnmethod = new TTMethod(typeConsole, "Warn", new TTArg[] { new TTArg(typeString, "_txt") }, typeVoid);
            var errormethod = new TTMethod(typeConsole, "Error", new TTArg[] { new TTArg(typeString, "_txt") }, typeVoid);

            typeConsole.AddMethod(logmethod);
            typeConsole.AddMethod(warnmethod);
            typeConsole.AddMethod(errormethod);
        }
        public static Module ttlangCore
        {
            get;
            private set;
        }

    }

}
